<?php

namespace app\index\controller;

use app\common\controller\Frontend;
use app\common\model\Config;
use think\Db;
use think\Log;
use think\Request;

class Index extends Frontend
{

    protected $noNeedLogin = '*';
    protected $noNeedRight = '*';
    protected $layout = '';

    public function index()
    {
        //$banner = Db('banner')->where(['status'=>'normal'])->order('id desc')->find();
        //$this->assign('banner',$banner);

        //文章分类
        /*
        if(null!==$this->request->param('cate')){
            $cate = $this->request->param('cate');
            $articles = Db('article')->where(['status'=>'normal','category_id'=>$cate])->order('id asc')->select();
        }else{
            $articles = Db('article')->where(['status'=>'normal'])->order('id asc')->select();
        }
        */

        if(null!==$this->request->param('cate')){
            $cate = $this->request->param('cate');
            $activetype = Db('activetype')->where(['id'=>$cate])->find();
            if(null==$activetype){
                $this->error('没有该活动');
            }
            
            $banner = $activetype;
            $this->assign('banner',$banner);
			$categorys = Db('category')->where(['status'=>'normal','activetype_id'=>$activetype['id']])->order('id asc,weigh desc')->select();
            $analysis = Db('analysis')->where(['activetype_id'=>$cate])->find();
            $this->assign('analysis',$analysis);

            if(null==$categorys){
                $this->error('没有该分类');
            }

        }else{
            //否则,永远显示第一个活动
            $activetype = Db('activetype')->where(['status'=>'normal'])->order('id asc')->find();

            $this->assign('cate',$activetype['id']);
            if(null==$activetype){
                $this->error('没有该活动');
            }

            $banner = $activetype;
            $this->assign('banner',$banner);


            $analysis = Db('analysis')->where(['activetype_id'=>$activetype['id']])->find();
            $this->assign('analysis',$analysis);

            $categorys = Db('category')->where(['status'=>'normal','activetype_id'=>$activetype['id']])->order('weigh desc,id asc')->select();
        }

        $this->assign('cate',$activetype['id']);
        $this->assign('activetype',$activetype);

        foreach($categorys as $ak=>$av){
            //如果这个分类下有文章，说明可以查看，否则是未发布
            $res = Db('article')->where(['status'=>'normal','category_id'=>$av['id']])->find();
            if($res){
                $categorys[$ak]['viewstatus'] = '点击查看';
                $categorys[$ak]['myview'] = 'yes';
            }else{
                $categorys[$ak]['viewstatus'] = '未发布';
                $categorys[$ak]['myview'] = 'no';
            }
        }
        $this->assign('categorys',$categorys);


        $jsapiTicket = $this->getJsApiTicket();
        //不对url进行过滤
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        $timestamp = time();
        $nonceStr = $this->createNonceStr();
        // // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
        $signature = sha1($string);
        $signpackage = array(
            "appId"     => config('site.appid'),
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        $this->assign('signpackage',$signpackage);


        //分享

        $myshare = Db('myshare')->where(['activetype_id'=>$activetype['id']])->find();
        if(null==$myshare){
            $myshare['name'] = config('site.name');
            $myshare['link'] = $this->request->domain();
            $myshare['description'] = config('site.name');
            $myshare['image'] = config('site.codeimg');
        }else{
            $myshare['image'] = $this->request->domain().$myshare['image'];
        }

        $this->assign('myshare',$myshare);
        //二维码
        $qrcode = Db('qrcode')->where(['activetype_id'=>$activetype['id']])->find();
        if(null==$qrcode){
            $qrcode['name'] = config('site.name');
            $qrcode['image'] = '';
        }
        $this->assign('qrcode',$qrcode);



        return $this->view->fetch();
    }

    public function getbase()
    {
        $redirect_url = $this->request->get('redirect_url');//获取前台传递的回调地址
        $appid = config('site.appid');//获取自己公众号的 appid
        //$redirect_uri = urlencode($redirect_url);//处理url
        $redirect_uri = $redirect_url;//处理url
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
        //$this->redirect($url,301);
        header("Location:{$url}");
    }


    //获取jsapiTicket
    private function getJsApiTicket() {
        $data = Db('weixin_token')
            ->where('type','jsapi_ticket')
            ->find();
        if($data['expire_time'] < time()){
            //       //如果数据库内令牌已失效 令牌有效期
            $accessToken = $this->getAccessToken();
            // print_r($accessToken);
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
            $res = $this->http_curl($url);
            $res = json_decode($res);


            if(!empty($res->errcode)){
                $res->remarks = 'api_ticket获取失败';
                die(json_encode($res));
            }


            if ($res->ticket) {
                Db('weixin_token')
                    ->where('type','jsapi_ticket')
                    ->update([
                        'expire_time'=> time()+7000,
                        'code'=>$res->ticket
                    ]);
            }
            return $res->ticket;
        }
        return $data['code'];
    }
    //获取AccessToken
    private function getAccessToken() {
        // access_token 应该全局存储与更新，以下代码以写入到文件中做示例
        $data = Db('weixin_token')
            ->where('type','access_token')
            ->find();
        // print_r($data);
        $appid = config('site.appid');
        $appsecret = config('site.appsecret');
        if($data['expire_time']<time()){
            //如果数据库内Token过期
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
            $res = json_decode($this->http_curl($url));
            //如果接口错误
            if(!empty($res->errcode)){
                $res->remarks = 'accessToken获取失败';
                die(json_encode($res));
            }
            $access_token = $res->access_token;
            //更新数据库内token
            if ($access_token) {
                Db('weixin_token')
                    ->where('type','access_token')
                    ->update([
                        'expire_time'=> time()+7000,
                        'code'=>$access_token
                    ]);
            }
            return $res->access_token;
        }
        return $data['code'];
    }





    //创建随机字符
    private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    //http获取
    public function  http_curl($url,$data=null){
        //1.初始化，创建一个新cURL资源
        $ch = curl_init();
        //2.设置URL和相应的选项
        curl_setopt($ch, CURLOPT_URL, $url);
        //curl_setopt($ch, CURLOPT_HEADER, 0);
        if(!empty($data)){
            curl_setopt($ch,CURLOPT_POST,1);

            curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
        }
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//禁止curl资源直接输出
        //3.抓取URL并把它传递给浏览器
        $res=curl_exec($ch);
        //4.关闭cURL资源，并且释放系统资源
        curl_close($ch);
        return $res;
    }

    public function getopenid()
    {
        //获取到网页授权的access_token
        //获取code后，请求以下链接获取access_token：  https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        $appid = config('site.appid');
        $appsecret = config('site.appsecret');

        $code = $this->request->post('code');
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$appsecret}&code={$code}&grant_type=authorization_code";
        //拉取用户的openid
        $res =$this->http_curl($url);

        $res = json_decode($res,true);
        $access_token = $res['access_token'];
        $openid = $res['openid'];
        $data['data']['openid'] = $openid;
        $data['data']['token'] = $access_token;
        echo json_encode($data);

    }



    public function isflow()
    {
        $openid = $this->request->post('openid');
        $access_token = $this->get_token();
        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$openid}&lang=zh_CN";
        $res =$this->http_curl($url);
        $res = json_decode($res,true);
        //Log::write($access_token);



        if($res['subscribe']==0){
            //未关注
            $info['data']['isFollow'] = $res['subscribe'];
            //把openid写入数据库
            $wxuser = Db('wxuser')->where(['openid'=>$res['openid']])->find();
            if($wxuser){
                Db('wxuser')->where(['id'=>$wxuser['id']])->update(['openid'=>$res['openid'],'access_token'=>$access_token,'subscribe'=>$res['subscribe'],'visittime'=>time()]);
                Db('wxuser')->where(['id'=>$wxuser['id']])->setInc('visitnum',1);
            }else{
                $res = Db('wxuser')->insert(['openid'=>$res['openid'],'access_token'=>$access_token,'subscribe'=>$res['subscribe'],'addtime'=>time()]);
            }

        }else{
            $info['data']['isFollow'] = $res['subscribe'];
            $info['data']['openid'] = $res['openid'];
            //把openid写入数据库
            $wxuser = Db('wxuser')->where(['openid'=>$res['openid']])->find();
            if($wxuser){
                Db('wxuser')->where(['id'=>$wxuser['id']])->update(['openid'=>$res['openid'],'access_token'=>$access_token,'subscribe'=>$res['subscribe'],'visittime'=>time()]);
                Db('wxuser')->where(['id'=>$wxuser['id']])->setInc('visitnum',1);
            }else{
                $res = Db('wxuser')->insert(['openid'=>$res['openid'],'access_token'=>$access_token,'subscribe'=>$res['subscribe'],'addtime'=>time()]);
            }

        }
        $cate = $this->request->post('cate');
        if(null!=$cate){
            Db('activetype')->where(['id'=>$cate])->setInc('dknum',1);
        }
        echo json_encode($info);
    }

    //获取token
    private function get_token(){
        $appid = config('site.appid');
        $appsecret = config('site.appsecret');
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
        $json=$this->http_curl($url);
        $result=json_decode($json);
        return $result->access_token;
    }

    public function weixin()
    {

        //这个echostr呢  只有说验证的时候才会echo  如果是验证过之后这个echostr是不存在的字段了
        if($this->request->get('echostr')){
            $echoStr = $this->request->get('echostr');
            if ($this->checkSignature()) {
                ob_clean();//防止之前缓存区数据影响
                echo $echoStr;
                exit;
            }
        }else{
            $this->responseMsg(); //如果没有echostr，则返回消息
        }
    }
    //验证微信开发者模式接入是否成功
    private function checkSignature()
    {
        //signature 是微信传过来的签名
        $signature = $this->request->get('signature');
        //微信发过来的时间戳
        $timestamp = $this->request->get('timestamp');
        //微信传过来的值随机字符串
        $nonce     = $this->request->get('nonce');
        //定义你在微信公众号开发者模式里面定义的token 这里举例为weixin
        $token  = "miao";
        //三个变量 按照字典排序 形成一个数组
        $tmpArr = array(
            $token,
            $timestamp,
            $nonce
        );
        // 字典排序
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        //哈希加密  在laravel里面是Hash::
        $tmpStr = sha1($tmpStr);
        //哈希加密后的数据 和微信服务器传过来的签名比较
        if ($tmpStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @name 消息接收
     * @author weikai
     */
    public function responseMsg()//执行接收器方法
    {
        //获取微信服务器的XML数据 转化为对象 判断消息类型
        $postStr = file_get_contents('php://input');
        if (!empty($postStr)){
            //将接收到的XML字符串写入日志， 用R标记表示接收消息
            Log::write("微信传递的数据".$postStr);
            //将接收的消息处理返回一个对象
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            //从消息对象中获取消息的类型 text  image location voice vodeo link
            $RX_TYPE = trim($postObj->MsgType);
            //消息类型分离, 通过RX_TYPE类型作为判断， 每个方法都需要将对象$postObj传入
            switch ($RX_TYPE){
                case "text":
                    $result = $this->receiveText($postObj);     //接收文本消息
                    break;
                case "image":
                    $result = $this->receiveImage($postObj);   //接收图片消息
                    break;
                case "location":
                    $result = $this->receiveLocation($postObj);  //接收位置消息
                    break;
                case "voice":
                    $result = $this->receiveVoice($postObj);   //接收语音消息
                    break;
                default:
                    $result = "unknown msg type: ".$RX_TYPE;   //未知的消息类型
            }
            //将响应的消息再次写入日志， 使用T标记响应的消息！
            $this->logger("T \n".$result);
            //输出消息给微信
            echo $result;
        }else{
            echo "";
            exit;
        }
    }

    //接收文本消息
    private function receiveText($object)
    {
        //从接收到的消息中获取用户输入的文本内容， 作为一个查询的关键字， 使用trim()函数去两边的空格
        $keyword = trim($object->Content);
        //自动回复模式
        if (strstr($keyword, "文本")){
            $content = "这是个文本消息";
        }else if(strstr($keyword, config('site.smkeyword'))){
            $keywordcontent = config('site.keywordcontent');
            $keywordurl = config('site.keywordurl');
            $content = "<a href='".$keywordurl."'>".$keywordcontent."</a>";
        }else{
            $content = date("Y-m-d H:i:s",time())."\n没有该消息";
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }

    //接收图片消息
    private function receiveImage($object)
    {
        $content = array("MediaId"=>$object->MediaId);
        $result = $this->transmitImage($object, $content);
        return $result;
    }
    //接收位置消息
    private function receiveLocation($object)
    {
        $content = "你发送的是位置，纬度为：".$object->Location_X."；经度为：".$object->Location_Y."；缩放级别为：".$object->Scale."；位置为：".$object->Label;
        $result = $this->transmitText($object, $content);
        return $result;
    }
    //接收语音消息
    private function receiveVoice($object)
    {
        if (isset($object->Recognition) && !empty($object->Recognition)){
            $content = "你刚才说的是：".$object->Recognition;
            $result = $this->transmitText($object, $content);
        }else{
            $content = array("MediaId"=>$object->MediaId);
            $result = $this->transmitVoice($object, $content);
        }

        return $result;
    }

    //回复文本消息
    private function transmitText($object, $content)
    {
        $xmlTpl = "<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[text]]></MsgType>
			<Content><![CDATA[%s]]></Content>
			</xml>";
        $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $result;
    }

    //回复图片消息
    private function transmitImage($object, $imageArray)
    {
        $itemTpl = "<Image>
			<MediaId><![CDATA[%s]]></MediaId>
			</Image>";

        $item_str = sprintf($itemTpl, $imageArray['MediaId']);

        $xmlTpl = "<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[image]]></MsgType>
			$item_str
			</xml>";

        $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
        return $result;
    }

    //回复语音消息
    private function transmitVoice($object, $voiceArray)
    {
        $itemTpl = "<Voice>
			<MediaId><![CDATA[%s]]></MediaId>
			</Voice>";

        $item_str = sprintf($itemTpl, $voiceArray['MediaId']);

        $xmlTpl = "<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[voice]]></MsgType>
			$item_str
			</xml>";

        $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
        return $result;
    }





    //日志记录,参数$log_content传日志的内容
    private function logger($log_content)
    {

        $max_size = 100000;   //声明日志的大小
        $log_filename = "log.xml";  //日志名称

        //如果文件存在并且大于了规定的最大大小就删除了
        if(file_exists($log_filename) && (abs(filesize($log_filename)) > $max_size)){
            unlink($log_filename);
        }

        //写入日志，内容前加上时间， 后面加上换行， 以追加的方式写入
        file_put_contents($log_filename, date('H:i:s')." ".$log_content."\n", FILE_APPEND);

    }






}
